//---------------------------------------------------------------------
// Authors: jachymko
//
// Description: Parameter name tab expansion
//
// Creation Date: Jan 17, 2007
//
//---------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Text;
using System.Text.RegularExpressions;

using BGShell.PowerShell.Commands;
using BGShell.PowerShell.TabExpansion.Parsers;

namespace BGShell.PowerShell.TabExpansion.Handlers
{
    partial class ParameterNameHandler : TabExpansionHandler
    {
        public ParameterNameHandler(GetTabExpansionCommand command)
            : base(command)
        {
        }

        public override bool TryExpand(string line, string word)
        {
            Match m = _pattern.Match(word);

            if (m.Success)
            {
                string command = TabExpansionParser.ExtractLastStatement(line);
                string pattern = m.Groups["Param"].Value;

                CommandInfo commandInfo = ResolveAlias(command);

                if (command != null)
                {
                    var pms = ExpandParameters(commandInfo, pattern);
                    WriteExpansions(pms);

                    return pms.Count == 0;
                }
            }

            return true;
        }


        private static List<String> ExpandParameters(CommandInfo command, string pattern)
        {
            var pms = new List<String>();

            foreach (string pn in GetParamNames(command))
            {
                if (pn.StartsWith(pattern, StringComparison.OrdinalIgnoreCase))
                {
                    pms.Add('-' + pn);
                }
            }

            return pms;
        }

        private static IEnumerable<String> GetParamNames(CommandInfo command)
        {
            CmdletInfo cmdlet = command as CmdletInfo;
            FilterInfo filter = command as FilterInfo;
            FunctionInfo function = command as FunctionInfo;

            if (cmdlet != null)
                return GetParamNames(cmdlet);

            if (filter != null)
                return GetParamNames(filter.Definition);

            if (function != null)
                return GetParamNames(function.Definition);

            return new string[0];
        }

        private static IEnumerable<String> GetParamNames(CmdletInfo cmdlet)
        {
            var returned = new Dictionary<String, Boolean>(StringComparer.OrdinalIgnoreCase);

            foreach (CommandParameterSetInfo set in cmdlet.ParameterSets)
            {
                foreach (CommandParameterInfo p in set.Parameters)
                {
                    if (!returned.ContainsKey(p.Name))
                    {
                        returned.Add(p.Name, true);
                        yield return p.Name;
                    }
                }
            }
        }

        private static IEnumerable<String> GetParamNames(string function)
        {
            foreach (FunctionParameter fp in new FunctionParameterParser(function).Parse())
            {
                yield return fp.Name;
            }
        }

        private static readonly Regex _pattern = new Regex(@"^-(?<Param>[\w0-9]*)");
    }
}
